<html>
<head>
<script src="../../resources/js-test.js"></script>
</head>
<body>
<div id="description"></div>
<div id="console"></div>

<script>
description("Tests XMLHttpRequest 'arraybuffer' loading with the .responseType and .response attributes.");

var xhr = 0;
var lastState = 0;

function stateChange() {
    // Protect against race-condition where .onreadystatechange sometimes will be called multiple times for the same state.
    if (xhr.readyState == lastState)
        return;
    lastState = xhr.readyState;
    
    if (xhr.readyState == XMLHttpRequest.DONE) {
        // Check that .response exists when .readyState is DONE
        if (xhr.response)
            testPassed("'arraybuffer' .response exists when .readyState is " + xhr.readyState + ".");
        else
            testFailed("'arraybuffer' .response should exist when .readyState is " + xhr.readyState + ".");
    } else {
        // Otherwise, for 'arraybuffer' the .response should not yet exist.
        if (!xhr.response)
            testPassed("'arraybuffer' .response does not exist when .readyState is " + xhr.readyState + ".");
        else
            testFailed("'arraybuffer' .response should not exist when .readyState is " + xhr.readyState + ".");
    }
}

function logBytesAtOffset(buffer8, offset) {
    var s = "bytes at offset " + offset + " : ";
    for (var i = 0; i < 8; ++i)
        s += buffer8[i + offset].toString(16) + ' ';
    
    debug(s);
}

function load() {
    testPassed('DONE LOADING');
    testPassed('received response object : ' + xhr.response + ".");

    // Make sure exception is thrown if responseType is set too late in the loading process.
    try {
        xhr.responseType = "text";
    } catch(e) {
        testPassed("exception correctly thrown when xhr.responseType is set to valid value too late in the loading process : " + e + ".");
    }

    var buffer = xhr.response;

    // Interpret the ArrayBuffer as Uint8Array.
    var buffer8 = new Uint8Array(buffer);
    buffer8.set(buffer);

    var totalLength = buffer8.length;
    debug('response length : ' + totalLength + ".");
    
    // Log the bytes at the start, in the middle, and near the end:
    logBytesAtOffset(buffer8, 0);
    logBytesAtOffset(buffer8, 0x5720A);
    logBytesAtOffset(buffer8, 0xA39D6);
    
    // Calculate checksum.
    var sum = 0;
    for (var i = 0; i < totalLength; ++i) {
        sum += buffer8[i];
    }
    
    debug('checksum : ' + sum);

    // Check that xhr.responseText throws an exception:
    try {
        var x = xhr.responseText;
    } catch(e) {
        testPassed("exception correctly thrown when xhr.responseText is accessed but responseType is 'arraybuffer' : " + e + ".");
    }

    // Check that xhr.responseXML throws an exception:
    try {
        var x = xhr.responseXML;
    } catch(e) {
        testPassed("exception correctly thrown when xhr.responseXML is accessed but responseType is 'arraybuffer' : " + e + ".");
    }
    
    // Test .response garbage collection.
    xhr.response.foo = "bar";
    gc();
    shouldBe("xhr.response.foo", "'bar'");    

    xhr = null;
    finishJSTest();
}

function runTest() {
    if (window.testRunner) {
        testRunner.dumpAsText();
        testRunner.waitUntilDone();
    }

    xhr = new XMLHttpRequest();
    xhr.onreadystatechange = stateChange;
    xhr.onload = load;
    xhr.open("GET", "../../http/tests/resources/balls-of-the-orient.aif", true);
        
    try {
        if ("responseType" in xhr)
            testPassed("responseType property exists.");

        if ("response" in xhr)
            testPassed("response property exists.");
            
        if (xhr.responseType == "")
            testPassed("xhr.responseType is initially set to default value of empty string.");

        // Make sure we can set responseType to valid values before send() is called.
        try {
            xhr.responseType = "";
            if (xhr.responseType == "")
                testPassed("xhr.responseType has been correctly set to ''.");

            xhr.responseType = "text";
            if (xhr.responseType == "text")
                testPassed("xhr.responseType has been correctly set to 'text'.");

            xhr.responseType = "document";
            if (xhr.responseType == "document")
                testPassed("xhr.responseType has been correctly set to 'document'.");

            xhr.responseType = "arraybuffer";
            if (xhr.responseType == "arraybuffer")
                testPassed("xhr.responseType has been correctly set to 'arraybuffer'.");
        } catch(e) {
            testFailed("unable to set xhr.responseType to a valid value " + e + ".");
        }
    } catch(e) {
        testFailed("Caught exception " + e + ".");
    }

    xhr.send(null);
    window.jsTestIsAsync = true;
}

runTest();

</script>

</body>
</html>
